package com.kadron.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.intercept.BypassInterceptors;

import com.kadron.common.KUtil;
import com.kadron.common.KeyValue;
import com.kadron.entity.User;
import com.kadron.enumeration.UserType;

@AutoCreate
@Name("userDAO")
@BypassInterceptors
public class KUserDAO extends KDAO<User> {

	public User find(long userId) {
		StringBuffer buffer = new StringBuffer(
				"SELECT u_ FROM User u_ WHERE u_.id = :id");
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
		query.setParameter("id", userId);
		try {			
			return (User) query.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}
	
	public Long getMaxOrdinal() {
		StringBuffer buffer = new StringBuffer(
		"SELECT MAX(u_.ordinal) FROM User u_ ");
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
		try {			
			return (Long) query.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}
	
	public User findByUsername(String username) {
		EntityManager em = getEntityManager();
		StringBuffer buffer = new StringBuffer(
		"SELECT u_ FROM User u_ WHERE u_.username = :username");
		javax.persistence.Query query = em.createQuery(buffer.toString());
		query.setParameter("username", username);
		try {			
			return (User) query.getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}
	
	public boolean check(String username,String email) {
		EntityManager em = getEntityManager();
		StringBuffer buffer = new StringBuffer(
		"SELECT 1 FROM User u_ WHERE u_.username = :username or u_.email=:email");
		javax.persistence.Query query = em.createQuery(buffer.toString());
		query.setParameter("username", username);
		query.setParameter("email", email);
		boolean exist = false;
		try {
			Integer one = (Integer) query.getSingleResult();
			if (one != null) {				
				exist = one.equals(1);			
			}
		} catch (NoResultException e) {
			if (log.isDebugEnabled()) {
				log.debug("User with usernaem="+username+" and email="+email+" were not found!");
			}
			exist = false;
		}
		return exist;
	}
	
	public User findByEmail(String email) {
		EntityManager em = getEntityManager();
		StringBuffer buffer = new StringBuffer(
		"SELECT u_ FROM User u_ WHERE u_.email = :email");
		javax.persistence.Query query = em.createQuery(buffer.toString());
		query.setParameter("email", email);
		try {
			return (User) query.getSingleResult();			
		} catch (NoResultException e) {
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<User> users(int stranica) {
		EntityManager em = getEntityManager();
		StringBuffer buffer = new StringBuffer(
		"SELECT k_ FROM User k_ ");
		javax.persistence.Query query = em.createQuery(buffer.toString());
		query.setFirstResult(stranica*50);
		query.setMaxResults(50);
        return query.getResultList();
	}
	
	public User find(String username,String lozinka,boolean active) {
		EntityManager em = getEntityManager();
		StringBuffer buffer = new StringBuffer(
				"SELECT k_ FROM User k_ WHERE " +
				"k_.username = :username AND " +
				"k_.lozinka = :lozinka AND " +
				"k_.aktivan = true ");
		javax.persistence.Query query = em.createQuery(buffer.toString());
		query.setParameter("username", username);
		query.setParameter("lozinka", lozinka);
		try {
			User k_ = (User) query.getSingleResult();
			return k_;			
		} catch (NoResultException e) {
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<User> pronadji(String ime,String prezime,String email,String city,String zip,String drzava_sifra,
			int max,int strana,org.hibernate.Session hs) {
		Query query = pripremi(ime, prezime, email, city, zip, drzava_sifra, max, strana, hs, false);
		
		List<User> list = query.getResultList();
		return list;
	}
	
	public long count(String ime,String prezime,String email,String city,String zip,String drzava_sifra,
			int max,int strana,org.hibernate.Session hs) {
		Query query = pripremi(ime, prezime, email, city, zip, drzava_sifra, max, strana, hs, true);
		try {			
			return (Long) query.getSingleResult();
		} catch (NoResultException e) {
			return 0;
		}
	}
	
	public javax.persistence.Query pripremi(
			String ime, 
			String prezime, 
			String email, 
			String city, 
			String zip, 
			String drzava_sifra, 
			int max_rezultat,
			int strana,
			org.hibernate.Session hs, boolean count) {
		List<KeyValue> parametri = new ArrayList<KeyValue>();
		
		boolean where = false;
		StringBuffer buffer = new StringBuffer();
		if (count) {
			buffer.append("SELECT COUNT(DISTINCT k_.sifra) FROM User k_ ");
		} else {
			buffer.append("SELECT DISTINCT k_ FROM User k_ ");			
		}
		
		if (!KUtil.isEmpty(ime)) {
			if (!where) {
				buffer.append(" WHERE ");				
				where = true;
			} else {
				buffer.append(" AND ");								
			}
			buffer.append(" k_.ime LIKE :ime ");
			parametri.add(new KeyValue("ime", (ime+"%")));
		}
		if (!KUtil.isEmpty(prezime)) {
			if (!where) {
				buffer.append(" WHERE ");				
				where = true;
			} else {
				buffer.append(" AND ");								
			}
			buffer.append(" k_.prezime like :prezime ");
			parametri.add(new KeyValue("prezime", (prezime+"%")));
		}
		if (!KUtil.isEmpty(drzava_sifra)) {
			if (!where) {
				buffer.append(" WHERE ");				
				where = true;
			} else {
				buffer.append(" AND ");								
			}
			buffer.append(" k_.drzava.a3 = :zemlja ");
			parametri.add(new KeyValue("zemlja", drzava_sifra));
		}
		if (!KUtil.isEmpty(email)) {
			if (!where) {
				buffer.append(" WHERE ");				
				where = true;
			} else {
				buffer.append(" AND ");								
			}
			buffer.append(" k_.email like :email ");
			parametri.add(new KeyValue("email", (email+"%")));
		}
		
		if (!KUtil.isEmpty(city)) {
			if (!where) {
				buffer.append(" WHERE ");				
				where = true;
			} else {
				buffer.append(" AND ");								
			}
			buffer.append(" k_.city like :city ");
			parametri.add(new KeyValue("city", (city+"%")));
		}
		buffer.append(" ORDER BY k_.created DESC");
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
		for (KeyValue kv : parametri) {
			query.setParameter(kv.getKey(), kv.getValue());
		}
		if (!count) {
			query.setMaxResults(max_rezultat);
			query.setFirstResult(strana*max_rezultat);			
		}
		return query;
	}

	public UserType getUserType(long userId) {
		StringBuffer buffer = new StringBuffer(
		"SELECT k_.userType FROM User k_ WHERE k_.id="+userId);
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
        return (UserType) query.getSingleResult();
	}
	
	@SuppressWarnings("unchecked")
	public List<User> getNewsletterUsers(long newsletterId) {
		StringBuilder builder = new StringBuilder(
				"SELECT e FROM User e WHERE e.newsletter = TRUE ");
		builder.append(" AND NOT EXISTS(SELECT 1 FROM UserNewsletter un WHERE un.userId=e.id AND un.newsletterId=:newsletter_id) ");
		builder.append(" AND e.blocked = FALSE");
		javax.persistence.Query query = getEntityManager().createQuery(builder.toString());
		query.setParameter("newsletter_id", newsletterId);
		return query.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<Long> getUsersForUpdateType(Date moment) {
		Date yearAgo = KUtil.getYearAgo(moment);
		Date monthAgo = KUtil.getMonthAgo(moment);
		StringBuffer buffer = new StringBuffer(
		"SELECT e.id FROM User e WHERE ((e.userType IN (3,4,5) AND e.statusUpdate <= :yearAgo) OR (e.userType = 2 AND e.statusUpdate <= :monthAgo))");
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
		query.setParameter("yearAgo", yearAgo);
		query.setParameter("monthAgo", monthAgo);
		return query.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<User> getAdminUsers() {
		StringBuffer buffer = new StringBuffer(
		"SELECT e FROM User e WHERE e.admin = TRUE AND e.blocked = FALSE");
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
		return query.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	public List<User> getBirthdayNearUsers(Date moment) {
		Date forSevenDays = KUtil.getBirthdayDays(moment);
		StringBuffer buffer = new StringBuffer(
		"SELECT e FROM User e WHERE DAY(e.birthday) = DAY(:forSevenDays) AND MONTH(e.birthday) = MONTH(:forSevenDays) AND e.blocked = FALSE");
		javax.persistence.Query query = getEntityManager().createQuery(buffer.toString());
		query.setParameter("forSevenDays", forSevenDays);
		return query.getResultList();
	}
	
}
